package com.justindav1s.homecontrol;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;


public class MainActivity extends ActionBarActivity implements BluetoothEventListener {


    private static final  int REQUEST_ENABLE_BT = 100;

    private Button pairButton = null;
    private Button connectButton = null;
    private TextView dataTextView = null;
    private BluetoothAdapter mBluetoothAdapter = null;
    private Set<String> mArrayAdapter = new HashSet<String>();
    private BluetoothDevice HC06 = null;
    private boolean paired = false;
    private boolean connected = false;
    private UUID uuid = null;
    private BluetoothInteractionManager btInteractionManager = null;
    private BluetoothDiscovery bluetoothDiscovery = null;
    private BluetoothConnectionManager bluetoothConnectionManager = null;
    private BluetoothEventListener bluetoothEventListener = null;
    private Buttons onOffButtons = null;

    private Handler messageHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message message) {
            Log.d(Constants.LOGTAG, "MESSAGE : "+message);
            if (Constants.CONNECTED_MSG_TYPE.equals(message.getData().get(Constants.TYPE)))  {
                Log.d(Constants.LOGTAG, "MESSAGE TYPE : "+message.getData().get(Constants.TYPE));
                BluetoothSocket socket = bluetoothConnectionManager.mmSocket;
                Log.d(Constants.LOGTAG, "SOCKET : "+socket);
                bluetoothConnected(socket);
            }
            else if (Constants.DISCONNECTED_MSG_TYPE.equals(message.getData().get(Constants.TYPE)))  {
                Log.d(Constants.LOGTAG, "MESSAGE TYPE : "+message.getData().get(Constants.TYPE));
                Log.d(Constants.LOGTAG, "MESSAGE CONTENT : "+message.getData().get(Constants.CONTENT));
                bluetoothData((String)message.getData().get(Constants.CONTENT));
            }
            else if (Constants.DATA_MSG_TYPE.equals(message.getData().get(Constants.TYPE)))  {
                Log.d(Constants.LOGTAG, "MESSAGE TYPE : "+message.getData().get(Constants.TYPE));
                Log.d(Constants.LOGTAG, "MESSAGE CONTENT : "+message.getData().get(Constants.CONTENT));
                bluetoothData((String)message.getData().get(Constants.CONTENT));
            }
            return true;
        }
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().commit();
        }

        bluetoothEventListener = this;

        connectButton = (Button) findViewById(R.id.connectButton);
        connectButton.setEnabled(false);
        connectButton.setText(Constants.CONNECT);
        connectButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Log.d(Constants.LOGTAG, "Connect Button Clicked !");
                connectButton.setText(Constants.CONNECTING);
                bluetoothConnectionManager.start();
            }
        });

        onOffButtons = new Buttons(this);
        onOffButtons.initialise();
    }

    @Override
    protected void onStart()    {
        Log.d(Constants.LOGTAG, "OnStart");
        super.onStart();
        this.pair("HC-06");
    }

    @Override
    protected void onPause()    {
        super.onPause();
        Log.d(Constants.LOGTAG, "OnPause");
        Log.d(Constants.LOGTAG, "Closing connection ...");
        bluetoothConnectionManager.close();
        connectButton.setEnabled(true);
        onOffButtons.setEnabledAll(false);
        connectButton.setText(Constants.CONNECT);
    }

    @Override
    protected void onRestart()    {
        Log.d(Constants.LOGTAG, "onRestart");
        super.onRestart();
        Log.d(Constants.LOGTAG, "Closing connection ...");
        bluetoothConnectionManager.close();
        connectButton.setEnabled(true);
        onOffButtons.setEnabledAll(false);
        connectButton.setText(Constants.CONNECT);
    }

    @Override
    protected void onResume()    {
        Log.d(Constants.LOGTAG, "onResume");
        super.onResume();
        Log.d(Constants.LOGTAG, "Closing connection ...");
        bluetoothConnectionManager.close();
        connectButton.setEnabled(true);
        onOffButtons.setEnabledAll(false);
        connectButton.setText(Constants.CONNECT);
    }

    @Override
    protected void onStop()    {
        Log.d(Constants.LOGTAG, "OnStop");
        super.onStop();
    }

    @Override
    protected void onDestroy()    {
        Log.d(Constants.LOGTAG, "OnDestroy");
        super.onDestroy();
    }

    @Override
    public void onActivityResult (int requestCode, int resultCode, Intent data) {
        Log.d(Constants.LOGTAG,"onActivityResult RequestCode : "+requestCode+" ResultCode : "+resultCode);
        Log.d(Constants.LOGTAG,"onActivityResult RequestCode : "+data.getData());
        bluetoothDiscovery = new BluetoothDiscovery(mBluetoothAdapter, this);
        pairButton.setEnabled(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        switch (item.getItemId()) {
            case R.id.action_settings:
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void bluetoothConnected(BluetoothSocket _socket) {
        connectButton.setText(Constants.CONNECTED_TO+HC06.getName());
        connected = true;
        btInteractionManager = new BluetoothInteractionManager(_socket, messageHandler);
        btInteractionManager.start();
        onOffButtons.setEnabledAll(true);
    }

    public void bluetoothData(String data)  {
        Log.d(Constants.LOGTAG, "Data Received : ["+data+"]");
    }

    @Override
    public void sendCode(byte[] _code)  {
        Log.d(Constants.LOGTAG, "Sendiing : ["+new String(_code)+"]");
        btInteractionManager.write(_code);
    }

    public void bluetoothDisconnected(String message) {
        connectButton.setText(Constants.NOT_CONNECTED);
        connected = false;
        btInteractionManager.close();
    }

    @Override
    public void deviceDiscovered(BluetoothDevice _device)   {
        Log.d(Constants.LOGTAG, "Device discovered : "+_device.getName());
        if (mBluetoothAdapter.isDiscovering())  {
            bluetoothDiscovery.stopDiscovery();
        }
        if (_device == null)    {
            pairButton.setText(Constants.PAIR);
        }
        else if (_device.getName().startsWith("HC"))  {
            Log.d(Constants.LOGTAG, "JY-MCU Found !! Name : "+_device.getName());
            HC06 = _device;
            paired = true;
            connected = false;
            pairButton.setText(Constants.PAIRED_TO+HC06.getName());
            connectButton.setEnabled(true);
        }
    }


    private void pair(String _deviceName)  {

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            Log.d(Constants.LOGTAG, "Bluetooth NOT supported.");
        }
        else    {
            Log.d(Constants.LOGTAG, "Bluetooth SUPPORTED !");
        }

        pairButton = (Button) findViewById(R.id.pairButton);
        pairButton.setEnabled(false);
        pairButton.setText(Constants.PAIR);
        pairButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Log.d(Constants.LOGTAG, "Pair Button Clicked !");
                pairButton.setText(Constants.PAIRING);
                mBluetoothAdapter.startDiscovery();
            }
        });

        if (!mBluetoothAdapter.isEnabled()) {
            Log.d(Constants.LOGTAG, "Enabling Bluetooth ....");
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            Log.d(Constants.LOGTAG, "Bluetooth now Enabled !");
        }
        else {
            Log.d(Constants.LOGTAG, "Bluetooth already Enabled !");
            bluetoothDiscovery = new BluetoothDiscovery(mBluetoothAdapter, this);
            pairButton.setEnabled(true);
        }

        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        // If there are paired devices
        if (pairedDevices.size() > 0) {
            // Loop through paired devices
            for (BluetoothDevice device : pairedDevices) {
                // Add the name and address to an array adapter to show in a ListView
                Log.d(Constants.LOGTAG, "Bluetooth device :"+device.getName() + "-" + device.getAddress());
                mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                if (device.getName().equalsIgnoreCase(_deviceName))  {
                    Log.d(Constants.LOGTAG, "JY-MCU Found !! Name : "+device.getName());
                    HC06 = device;
                    paired = true;
                    pairButton.setText(Constants.PAIRED_TO+HC06.getName());
                    pairButton.setEnabled(true);
                    connectButton.setEnabled(true);
                    connectButton.setText(Constants.CONNECT);
                }
                else    {
                    Log.d(Constants.LOGTAG, "JY-MCU NOT Found !!");
                    paired = false;
                    pairButton.setText(Constants.NOT_PAIRED);
                    connectButton.setText(Constants.NOT_CONNECTED);
                }
            }
        }
        else    {
            Log.d(Constants.LOGTAG, "No paired Devices ....");
            pairButton.setText(Constants.NOT_PAIRED);
            connectButton.setText(Constants.NOT_CONNECTED);
            paired = false;
        }

        uuid = getUUID();
        bluetoothConnectionManager = new BluetoothConnectionManager(messageHandler, mBluetoothAdapter, HC06, uuid);
    }

    private UUID getUUID()    {
        final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);

        final String tmDevice, tmSerial, androidId;
        tmDevice = "" + tm.getDeviceId();
        tmSerial = "" + tm.getSimSerialNumber();
        androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);

        UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
        String deviceId = deviceUuid.toString();
        Log.d(Constants.LOGTAG, "UUID : "+deviceId);
        return  deviceUuid;
    }
}
